package com.tc.banana.framework;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tc.banana.framework.annotation.Service;
import com.tc.banana.framework.util.ReflectionUtil;

/** 
 * @author  wdd 
 * @date 创建时间：2016年4月3日 下午2:08:28 
 */
public final class BeanHelper {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(BeanHelper.class);
	private static final Map<Class<?>, Object> BEAN_MAP = new HashMap<Class<?>, Object>();
	
	static {
		Set<Class<?>> beanClassSet = ClassHelper.getBeanClassSet();
		for (Class<?> cls : beanClassSet) {
			BEAN_MAP.put(cls, ReflectionUtil.newInstance(cls));
		}
	}

	public static Map<Class<?>, Object> getBeanMap() {
		return BEAN_MAP;
	}
	
	public static <T> T getBean(Class<T> cls) {
		return getBean(cls, BEAN_MAP);
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<T> cls, String name) {
		Object obj = getBean(name, BEAN_MAP);
		if (obj.getClass().isAssignableFrom(cls))
			return (T) obj;
		LOGGER.error("no type of "+cls+"bean named " + name);
		throw new RuntimeException("no type of "+cls+"bean named " + name);
	}
	
	@SuppressWarnings("unchecked")
	private static <T> T getBean(Class<T> cls, Map<Class<?>, Object> beanMap) {
		if (!BEAN_MAP.containsKey(cls)) {
			LOGGER.error("can not get bean by class "+ cls);
			throw new RuntimeException("can not get bean by class "+ cls);
		}
		return (T) BEAN_MAP.get(cls);
	}
	
	public static Object getBean(String beanName, Map<Class<?>, Object> beanMap) {
		for (Class<?> cls : beanMap.keySet()) {
			if (cls.isAnnotationPresent(Service.class)){
				String name = cls.getAnnotation(Service.class).value();
				if(beanName.equalsIgnoreCase(name) || cls.getSimpleName().equalsIgnoreCase(beanName)){
					return getBean(cls, beanMap);
				}
			}
		}
		LOGGER.error("no bean named "+ beanName);
		throw new RuntimeException("no bean named "+ beanName);
	}
	
	public static Object getInterfaceImplBean(Class<?> source, Map<Class<?>, Object> beanMap){
		for (Class<?> cls : beanMap.keySet()) {
			if (source.isAssignableFrom(cls)) {
				return beanMap.get(cls);
			}
		}
		LOGGER.error("no bean impled from interface "+ source.getSimpleName());
		throw new RuntimeException("no bean impled from interface "+ source.getSimpleName());
	}
	
}
